<?php
// require_once __DIR__.'/autoload.php';

// use Workerman\Worker;
// use Protocols\DHT;
// use common\Base;
// use Workerman\Connection\AsyncUdpConnection;
// use Workerman\Lib\Timer;
// use common\Log;


$server = stream_socket_server('udp://127.0.0.1:22622');
// $server2 = stream_socket_server('udp://0.0.0.0:2262');


exit;

// $nid = Base::get_node_id();
// $offset = 0;
// while($offset<20){

//     echo "******************\n";
//     $k = $nid[$offset];
//     var_dump($k);

//     var_dump(ord($k));

//     var_dump(chr(ord($k)));

//     $offset++;
// }

// exit;

// $test['error']['generic'] = '{"t":"aa", "y":"e", "e":[201, "A Generic Error Ocurred"]}';
// $test['error']['bencode'] = 'd1:eli201e23:A Generic Error Ocurrede1:t2:aa1:y1:ee';


// $test['ping']['generic'] = '{"t":"aa", "y":"q", "q":"ping", "a":{"id":"abcdefghij0123456789"}}';
// $test['ping']['bencode'] = 'd1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe';


// $test['ping_response']['generic'] = '{"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}';
// $test['ping_response']['bencode'] = 'd1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re';

// $test['find_node']['generic'] = '{"t":"aa", "y":"q", "q":"find_node", "a": {"id":"abcdefghij0123456789", "target":"mnopqrstuvwxyz123456"}}';
// $test['find_node']['bencode'] = 'd1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe';

// $test['find_node_response']['generic'] = '{"t":"aa", "y":"r", "r": {"id":"0123456789abcdefghij", "nodes": "def456..."}}';
// $test['find_node_response']['bencode'] = 'd1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re';

// $test['get_peers']['generic'] = '{"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}}';
// $test['get_peers']['bencode'] = 'd1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe';

// $test['get_peers_response_with_peers']['generic'] = '{"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "values": ["axje.u", "idhtnm"]}}';
// $test['get_peers_response_with_peers']['bencode'] = 'd1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:axje.u6:idhtnmee1:t2:aa1:y1:re';

// $test['get_peers_response_with_nodes']['generic'] = '{"t":"aa", "y":"r", "r": {"id":"abcdefghij0123456789", "token":"aoeusnth", "nodes": "def456..."}}';
// $test['get_peers_response_with_nodes']['bencode'] = 'd1:rd2:id20:abcdefghij01234567895:nodes9:def456...5:token8:aoeusnthe1:t2:aa1:y1:re';

// $test['announce_peers']['generic'] = '{"t":"aa", "y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "implied_port": 1, "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}}';
// $test['announce_peers']['bencode'] = 'd1:ad2:id20:abcdefghij012345678912:implied_porti1e9:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe';

// $test['announce_peers_response']['generic'] = '{"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}';
// $test['announce_peers_response']['bencode'] = 'd1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re';

// $test['on_error_missing']['test']['g'] = '{"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}';
// $test['on_error_missing']['test']['b'] = 'd1:rd2:id20:mnopqrstuvwxyz123456e1:t1:y1:re';


// class test
// {
//     public function onError($connection,$code,$msg){
//         echo "on error : $code $msg\n";
//     }
// }

// $test_obj = new Test();

// foreach ($test as $t_key => $t_value) {
//     echo '+-------------------------------------+'.PHP_EOL;
//     echo "|test          | {$t_key}|\n";
//     if(isset($t_value['bencode'])){
//         $return = DHT::decode($t_value['bencode'],$test_obj);
        
//         if($return == json_decode($t_value['generic'],true)){
//             echo "|decode result | passed|\n";
//         }else{
//             echo "|decode result | error|\n";
//         }
//         $return = DHT::encode(json_decode($t_value['generic'],true),$test_obj);
    
//         if($return == $t_value['bencode']){
//             echo "|encode result | passed|\n";
//         }else{
//             echo "|encode result | error|\n";
//         }
//     }else{
//         echo "|decode result | none|\n";
//         echo "|encode result | none|\n";
//     }

//     if(isset($t_value['test'])){
//         DHT::decode($t_value['test']['g'],$test_obj);
//         DHT::encode(json_encode($t_value['test']['g']),$test_obj);
//     }else{
        
//     }

//     // echo '+-------------------------------------+'.PHP_EOL;
//     echo "\n";
// }

$server = new Worker('udp://0.0.0.0:4788');

$server->protocol = new DHT();

$server->bootstrap_nodes = array(
    array('router.bittorrent.com', 6881),
    array('dht.transmissionbt.com', 6881),
    array('router.utorrent.com', 6881)
);

$server->table = [];

$server->nid = Base::get_node_id();

$server->config = require_once __DIR__.'/config/config.php';

$server->joinDht = function() use ($server){
    if(count($server->table) == 0){
        foreach($server->bootstrap_nodes as $node){
            //echo '路由表为空 将自身伪造的ID 加入预定义的DHT网络 '.$node[0].PHP_EOL;
            $server->findNode("udp://".gethostbyname($node[0]).":".$node[1]); //将自身伪造的ID 加入预定义的DHT网络
        }
    }
};

$server->findNode = function($address,$id = null) use ($server){

    if(is_null($id)){
        $mid = Base::get_node_id();
    }else{
        $mid = Base::get_neighbor($id, $nid); // 否则伪造一个相邻id
    }
    $msg = array(
        't' => Base::entropy(2),
        'y' => 'q',
        'q' => 'find_node',
        'a' => array(
            'id' => $server->nid,
            'target' => $mid
        )
    );

    $find_conn = new AsyncUdpConnection($address);

    $find_conn->protocol = new DHT();

    $find_conn->onConnect = function($find_conn) use ($msg){
        $find_conn->send($msg);
    };

    $find_conn->connect();


};

$server->onWorkerStart = function() use ($server){
    Log::record('server start');
    // $server->joinDht();
};


Worker::runAll();